package pers.hl.library.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import pers.hl.library.common.Const;
import pers.hl.library.common.CustomException;
import pers.hl.library.common.Response;
import pers.hl.library.common.base.LibBaseController;
import pers.hl.library.enums.FileType;
import pers.hl.library.po.*;
import pers.hl.library.service.*;
import pers.hl.library.utils.ExceptionHelper;
import pers.hl.library.utils.MyUtils;
import pers.hl.library.utils.QRFileSaveHelper;

import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("book")
public class BookController extends LibBaseController<Book> {

    @Autowired
    BookService bookService;
    @Autowired
    FileService fileService;
    @Autowired
    BookShareRecordService bookShareRecordService;
    @Autowired
    BookBorRecordService bookBorRecordService;
    @Autowired
    CollectService collectService;

    @Autowired
    public BookController(BookService bookService) {
        init(bookService);
    }

    /**
     * 书籍关键词搜索
     *
     * @param keywords 关键词
     */
    @GetMapping("search")
    public Response search(@RequestParam("keywords") String keywords) {
        if (null == keywords) {
            return Response.fail_400("搜索关键词不能为空");
        }
        return Response.ok(bookService.getDataList2("search", keywords));
    }

    @Override
    protected String getBussName() {
        return "书籍";
    }

    /**
     * 共享图书(新增图书信息)插入之前验证参数、设置书籍持有人id,即当前用户
     *
     * @param data 书籍信息
     */
    @Override
    protected void beforeAdd(Book data) {
        if (!MyUtils.idValid(data.getBookLibId())) {
            ExceptionHelper.throw400("图书馆id不能为空");
        }
        if (!MyUtils.idValid(data.getBookTag())) {
            ExceptionHelper.throw400("图书标签不能为空");
        }
        // 主键自增
        data.setBookId(null);
        data.setBookFileId(null);
        // 设置持有者为当前调用接口用户
        data.setBookOwner(getCurrentUser().getUserId());
        // 默认可借阅
        data.setBookStatus(Book.STATUS_ENABLE);
    }

    /**
     * 一、新增书籍成功后，根据其id和类型生成二维码，并保存及入库；
     * 二、新增书籍共享记录
     *
     * @param data 待新增的数据
     */
    @Override
    protected void afterAdd(Book data) throws Exception {
        // 生成二维码
        Integer bookId = data.getBookId();
        // 文件保存及入库
        QRFileSaveHelper.saveFile(FileType.BOOK_QRCODE.value(), bookId, fileService);

//        //这里采用主键id+文件type的形式作为二维码内容，满足多场景下扫码的需求
//        JsonObject object = new JsonObject();
//        object.addProperty("id", bookId);
//        object.addProperty("type", FileType.value(FileType.BOOK_QRCODE));
//        String content = GsonUtils.toJson(object);
//        logger.info("二维码保存的json串" + content);
//        File dest = QRCodeUtil.QREncode(content, Const.FilePath.QRCODE_PATH);
//        // 创建文件表对应实体，并写入数据库
//        FileEntity fileEntity = new FileEntity();
//        fileEntity.setFileType(FileType.value(FileType.BOOK_QRCODE));
//        fileEntity.setFileBussId(bookId);
//        fileEntity.setFileUrl(dest.getAbsolutePath());
//        Date curDate = new Date();
//        fileEntity.setFileCreateTime(curDate);
//        fileEntity.setFileUpdateTime(curDate);
//        if (!fileService.addData(fileEntity)) {
//            ExceptionHelper.throw500("书籍二维码数据入库失败");
//        }
//        // 入库成功后返回书籍二维码图片id,再更新书籍fileId
//        if (!bookService.updateFileId(data.getBookId(), fileEntity.getFileId())) {
//            ExceptionHelper.throw500("书籍二维码id写入失败");
//        }

        // 新增书籍共享记录
        BookShareRec shareRec = new BookShareRec();
        shareRec.setBsrUserId(getCurrentUser().getUserId());
        shareRec.setBsrCreateTime(new Date());
        shareRec.setBookId(bookId);
        if (!bookShareRecordService.addData(shareRec)) {
            ExceptionHelper.throw500("图书共享记录写入失败");
        }
    }

    /**
     * 执行书籍信息更新操作前要做的操作
     *
     * @param data 待更新的数据
     * @throws Exception
     */
    @Override
    protected void beforeUpdate(Book data) throws Exception {
        Integer bookId = data.getBookId();
        if (bookId == null || bookId <= 0) {
            ExceptionHelper.throw400("书籍id不能为空");
        }
    }

    /**
     * 修改书籍信息后，做的操作
     * @param data 待更新的数据
     * @throws Exception
     */
    @Override
    protected void afterUpdate(Book data) throws Exception {
    }

    @GetMapping("top5")
    public Response top5() {
        return Response.ok(bookService.getTop5());
    }

    /**
     * 获取我的借阅，包含借阅中和已借阅状态
     * @return
     */
    @GetMapping("myBorrows")
    public Response myBorrows() {
        return Response.ok(bookService.myBorrows(getCurrentUser().getUserId()));
    }

    /**
     * 书籍借阅
     *
     * 场景：A向B借阅，A扫描B出示的书籍二维码，调用接口)应当由非书籍持有人发起，若不是，则终止
     *
     * @param bookId 书籍id
     */
    @PostMapping("borrow/{bookId}")
    public Response borrow(@PathVariable("bookId") Integer bookId) {
        boolean ownerInvoke = bookOwnerInvoke(bookId);
        if (ownerInvoke) {
            throw new CustomException(Const.HttpStatusCode.HttpStatus_401, "书籍持有人无法发起借阅");
        }
        Book book = bookService.getDataByPrimaryId(bookId);
        if (book.getBookStatus() == BookBorRec.STATUS_BORROWING || book.getBookStatus() == BookBorRec.STATUS_BORROWED) {
            ExceptionHelper.throw403("当前书籍已被借阅，状态:" + book.getBookStatus());
        }
        BookBorRec bookBorRec = new BookBorRec();
        bookBorRec.setBbrBookId(bookId);
        bookBorRec.setBbrBorrower(getCurrentUser().getUserId());
        bookBorRec.setBbrTime(new Date());
        bookBorRec.setBbrStatus(BookBorRec.STATUS_BORROWING);
        bookService.updateStatus(bookId, BookBorRec.STATUS_BORROWING);
        if (bookBorRecordService.addData(bookBorRec)) {
            return Response.ok("借阅成功", bookBorRec);
        }
        return Response.fail_500("借阅失败");
    }

    /**
     * 是否书籍持有人调用
     * @param bookId
     * @return
     */
    private boolean bookOwnerInvoke(Integer bookId) {
        // 为了确保数据真实性及安全性，应以数据库信息为准
        Book dbData = bookService.getDataByPrimaryId(bookId);
        if (dbData == null) {
            throw new CustomException(Const.HttpStatusCode.HttpStatus_404, "未找到书籍信息");
        }
        Integer ownerId = dbData.getBookOwner();
        return ownerId.equals(getCurrentUser().getUserId());
    }

    /**
     * 取消借阅
     * @return
     */
    @PostMapping("cancel/{recordId}")
    public Response cancel(@PathVariable("recordId") Integer recordId) {
        Book book = getBookByRecordId(recordId);
        Integer bookId = book.getBookId();
        boolean ownerInvoke = bookOwnerInvoke(bookId);
        if (ownerInvoke) {
            ExceptionHelper.throw403("书籍持有人不可取消借阅");
        }
        if (book.getBookStatus() != BookBorRec.STATUS_BORROWING) {
            ExceptionHelper.throw403("当前书籍不可被取消，状态:" + book.getBookStatus());
        }
        bookService.updateStatus(bookId, BookBorRec.STATUS_CANCEL);
        if (bookBorRecordService.updateStatus(recordId, BookBorRec.STATUS_CANCEL)) {
            return Response.ok("取消成功");
        }
        return Response.fail_500("取消失败");
    }

    private Integer getBookIdByRecordId(Integer recordId) {
        BookBorRec record = bookBorRecordService.getDataByPrimaryId(recordId);
        if (record == null) {
            ExceptionHelper.throw400("未找到借阅记录");
        }
        return record.getBbrBookId();
    }

    private Book getBookByRecordId(Integer recordId) {
        BookBorRec record = bookBorRecordService.getDataByPrimaryId(recordId);
        return bookService.getDataByPrimaryId(record.getBbrBookId());
    }

    /**
     * 接受借阅
     *
     * @return
     */
    @PostMapping("accept/{recordId}")
    public Response accept(@PathVariable("recordId") Integer recordId) {
        Book book = getBookByRecordId(recordId);
        Integer bookId = book.getBookId();
        boolean ownerInvoke = bookOwnerInvoke(bookId);
        if (!ownerInvoke) {
            ExceptionHelper.throw403("非书籍持有人不可发起接受请求");
        }
        if (book.getBookStatus() != BookBorRec.STATUS_BORROWING) {
            ExceptionHelper.throw403("当前书籍借阅请求不可被接受，状态:" + book.getBookStatus());
        }
        bookService.updateStatus(bookId, BookBorRec.STATUS_BORROWED);
        if (bookBorRecordService.updateStatus(recordId, BookBorRec.STATUS_BORROWED)) {
            return Response.ok("接受成功");
        }
        return Response.fail_500("接受失败");
    }

    /**
     * 拒绝借阅
     * @return
     */
    @PostMapping("refuse/{recordId}")
    public Response refuse(@PathVariable("recordId") Integer recordId) {
        Book book = getBookByRecordId(recordId);
        Integer bookId = book.getBookId();
        boolean ownerInvoke = bookOwnerInvoke(bookId);
        if (!ownerInvoke) {
            ExceptionHelper.throw403("非书籍持有人不可发起拒绝请求");
        }
        if (book.getBookStatus() != BookBorRec.STATUS_BORROWING) {
            ExceptionHelper.throw403("当前书籍借阅请求不可被拒绝，状态:" + book.getBookStatus());
        }
        bookService.updateStatus(bookId, BookBorRec.STATUS_REFUSED);
        if (bookBorRecordService.updateStatus(recordId, BookBorRec.STATUS_REFUSED)) {
            return Response.ok("拒绝成功");
        }
        return Response.fail_500("拒绝失败");
    }

    /**
     * 归还图书
     * @return
     */
    @PostMapping("return/{recordId}")
    public Response returnBack(@PathVariable("recordId") Integer recordId) {
        Book book = getBookByRecordId(recordId);
        Integer bookId = book.getBookId();
        boolean ownerInvoke = bookOwnerInvoke(bookId);
        if (!ownerInvoke) {
            ExceptionHelper.throw403("非书籍持有人不可发起确认归还请求");
        }
        if (book.getBookStatus() != BookBorRec.STATUS_BORROWED) {
            ExceptionHelper.throw403("当前书籍不可被归还，状态:" + book.getBookStatus());
        }
        bookService.updateStatus(bookId, BookBorRec.STATUS_RETURNED);
        if (bookBorRecordService.updateStatus(recordId, BookBorRec.STATUS_RETURNED)) {
            return Response.ok("归还成功");
        }
        return Response.fail_500("归还失败");
    }

    /**
     * 我的发布记录
     */
    @GetMapping("myPublish")
    public Response myPublish() {
        return Response.ok(bookShareRecordService.myPublish(getCurrentUser().getUserId()));
    }

    /**
     * 我的分享
     *
     * 即借出去的书 （当前存在借阅记录并且借阅状态为已借阅(已接受)、已归还状态的书籍分享记录）
     */
    @GetMapping("sharing")
    public Response sharing(@RequestParam("userId") int userId) {
        if (userId <= 0) {
            ExceptionHelper.throw400("userId cannot be empty");
        }
        return Response.ok(bookShareRecordService.mySharing(userId));
    }

    /**
     * 我的收藏
     */
    @GetMapping("myCollect")
    public Response myCollect() {
        return Response.ok(bookService.myCollect(getCurrentUser().getUserId()));
    }

    /**
     * 收藏书籍
     * @param bookId
     * @return
     */
    @PostMapping("collect/{bookId}")
    public Response collect(@PathVariable("bookId") Integer bookId) {
        if (bookId < 0) {
            ExceptionHelper.throw400("参数错误");
        }
        if (collected(bookId)) {
            ExceptionHelper.throw400("您已经收藏该书籍");
        }
        Collect collect = new Collect();
        collect.setUserId(getCurrentUser().getUserId());
        collect.setBookId(bookId);
        collect.setCreateTime(new Date());
        if (collectService.addData(collect)) {
            return Response.ok("收藏成功");
        } else {
            return Response.fail_500("收藏失败");
        }
    }

    /**
     * 查询当前用户是否已收藏该书籍
     */
    private boolean collected(Integer bookId) {
        List<Collect> list =  collectService.getDataByUserBookId(bookId, getCurrentUser().getUserId());
        return list != null && list.size() > 0;
    }

    /**
     * 取消收藏
     * @param bookId
     * @return
     */
    @PostMapping("uncollect/{bookId}")
    public Response uncollect(@PathVariable("bookId") Integer bookId) {
        if (bookId < 0) {
            ExceptionHelper.throw400("参数错误");
        }
        if (!collected(bookId)) {
            ExceptionHelper.throw400("您尚未收藏该书籍");
        }
        if (collectService.deleteByBookId(bookId, getCurrentUser().getUserId())) {
            return Response.ok("取消收藏成功");
        } else {
            return Response.fail_500("取消收藏失败");
        }
    }

    /**
     * 查询书籍详情后
     * @param data
     */
    @Override
    protected void afterGetDataByPrimaryId(Book data) {
        // 添加是否收藏状态
        data.setCollect(collected(data.getBookId()) ? 1 : 0);
    }

    /**
     * 我的借阅，借阅到的
     * @return
     */
    @GetMapping("myBorrowed")
    public Response myBorrowed() {
        return Response.ok(bookService.myBorrowed(getCurrentUser().getUserId()));
    }

    /**
     * 扫码借阅
     * 场景：A向B借阅，A扫描B出示的书籍二维码，调用接口)应当由非书籍持有人发起，若不是，则终止
     * 等同于调用接受接口,更改状态为已借阅
     */
    @PostMapping("scanBorrow/{bookId}")
    public Response scanBorrow(@PathVariable("bookId") Integer bookId) {
        boolean ownerInvoke = bookOwnerInvoke(bookId);
        if (ownerInvoke) {
            ExceptionHelper.throw403("书籍持有人不可发起扫码借阅请求");
        }
        BookBorRec bookBorRec = getMyBorrowingRecByBookId(bookId);
        if (bookBorRec == null) {
            ExceptionHelper.throw403("未找到该书籍的借阅记录，请先发起借阅");
        }
        if (bookBorRec.getBbrStatus() != BookBorRec.STATUS_BORROWING) {
            ExceptionHelper.throw403("当前书籍不可被扫码借阅，状态:" + bookBorRec.getBbrStatus());
        }
        bookService.updateStatus(bookId, BookBorRec.STATUS_BORROWED);
        if (bookBorRecordService.updateStatus(bookBorRec.getBbrId(), BookBorRec.STATUS_BORROWED)) {
            return Response.ok("借阅成功");
        }
        return Response.fail_500("借阅失败");
    }

    private BookBorRec getMyBorrowingRecByBookId(Integer bookId) {
        return bookBorRecordService.getBorrowingRecord(getCurrentUser().getUserId(), bookId);
    }

    /**
     * 检查是否存在即将到期的借阅（距离到期时间<=5天）
     * 小于0则表示已经逾期
     */
    @GetMapping("checkExpiringRecord")
    public Response checkExpiringRecord() {
        User user = getCurrentUser();
        return Response.ok(bookBorRecordService.getExpiringRecords(user.getUserId()));
    }


}
